/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.lundberg.podcasts.types;

import java.text.ParseException;
import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.lundberg.podcasts.util.Util;

import android.database.Cursor;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.Log;


/**
 * A Channel Item
 * @author lundbergg
 */
public class Item implements Parcelable
{
	private static final Pattern DURATION_PATTERN = Pattern.compile("^(\\d*:)*(\\d*):(\\d*)$");
	
    public String guid;
    public int channel_id;
    public String title;
    // ISO8601 format
    private String pubDate;
    public boolean listened;
    public int position;
    public int size;
    private String duration;
    public String enclosureURL;
    private String description;

    
    public Item() {
    }
    
    
    public Item(Cursor cursor)
    {
    	readFromCursor(cursor);    	
    }
    
    
    public Item(String guid, int channel_id, String title, String pubDate,
                boolean listened, int position, int size, String duration,
                int queue_position, String enclosureURL, String description)
    {
    	this.guid = guid;
	    this.channel_id = channel_id;
	    this.title = title;
	    this.pubDate = pubDate;
	    this.listened = listened;
	    this.position = position;
	    this.size = size;
	    this.duration = duration;
	    this.enclosureURL = enclosureURL;
	    this.description = description;
    }
    
    
    public Item(Parcel in)
    {
    	this.guid = in.readString();
    	this.channel_id = in.readInt();
    	this.title = in.readString();
    	this.pubDate = in.readString();
    	this.listened = (in.readInt() == 1);
    	this.position = in.readInt();
    	this.size = in.readInt();
    	this.duration = in.readString();
    	this.enclosureURL = in.readString();
    	this.description = in.readString();
    }
    
    
    
    public void readFromCursor(Cursor cursor)
    {
    	int index = -1;
    	
    	if ((index = cursor.getColumnIndex("guid")) > -1) {
    		
    		this.guid = cursor.getString(index);
    	}
    	
		if ((index = cursor.getColumnIndex("channel_id")) > -1) {
		    		
			this.channel_id = cursor.getInt(index);
		}
		
		if ((index = cursor.getColumnIndex("title")) > -1) {
			
			this.title = cursor.getString(index);
		}
		
		if ((index = cursor.getColumnIndex("pubDate")) > -1) {
			
			this.pubDate = cursor.getString(index);
		}
		
		if ((index = cursor.getColumnIndex("listened")) > -1) {
			
			this.listened = (cursor.getInt(index) == 1);
		}
		
		if ((index = cursor.getColumnIndex("position")) > -1) {
			
			this.position = cursor.getInt(index);
		}
		
		if ((index = cursor.getColumnIndex("size")) > -1) {
			
			this.size = cursor.getInt(index);
		}
		
		if ((index = cursor.getColumnIndex("duration")) > -1) {
			
			setDuration(cursor.getString(index));
		}
		
		if ((index = cursor.getColumnIndex("enclosureURL")) > -1) {
			
			this.enclosureURL = cursor.getString(index);
		}
		
		if ((index = cursor.getColumnIndex("description")) > -1) {
			
			this.description = cursor.getString(index);
		}
    }

    
    
    public void setPubDate(String pubDate)
    {
    	try
	    {
	    	// ISO8601
	    	if (pubDate == null || Character.isDigit(pubDate.charAt(0)))
	    	{
	    		this.pubDate = pubDate;
	    	}
	    	// RFC 822
	    	else if (Character.isDigit(pubDate.charAt(pubDate.length()-1)))
	    	{
	    		Date rfc822Date = Util.RFC822_DATE_FORMAT_1.parse(pubDate);
	        	this.pubDate = Util.ISO8601_DATE_FORMAT.format(rfc822Date);
	    	}
	    	else
	    	{
	    		Date rfc822Date = Util.RFC822_DATE_FORMAT_2.parse(pubDate);
	        	this.pubDate = Util.ISO8601_DATE_FORMAT.format(rfc822Date);
	    	}
	    }
	    catch(ParseException e) {
	        e.printStackTrace();
	    }
    }
    
    
    public void setDescription(String description) {
    	
    	// Remove all HTML tags
    	if (description != null) {
    		
    		this.description = description.replaceAll("<[Bb][Rr]\\s*/>", "\n")
					.replaceAll("<script[^>]*>[^<]*</script>", "")
					.replaceAll("\\<[^>]*>", "")
					.replaceAll("&[Nn][Bb][Ss][Pp];", " ")
					.replaceAll("&#[0-9]*;", "")
					.replaceAll("\n{3,}", "\n\n")
					.replaceFirst("^\n+", "");
    	}
    	else {
    		
    		this.description = description;
    	}
    }
    
    
    public String getDescription() {
    	return this.description;
    }
    
    
    public void setDuration(String duration)
    {
    	// If the duration is not specified in HH:MM:SS format
	    if (duration != null)
	    {
			if (!duration.contains(":"))
			{
	            int seconds = Integer.parseInt(duration);
	            int hours = seconds / 3600;
	
	            seconds %= 3600;
	
	            int minutes = seconds / 60;
	
	            seconds %= 60;
	
	            this.duration = hours+":"
	                    +((minutes < 10) ? "0"+minutes : minutes)+":"
	                    +((seconds < 10) ? "0"+seconds : seconds);
			}
			else {
				
				this.duration = duration;
			}
	    }
	    else {
	
	        this.duration = "0:00:00";
	    }
    }
    
    
    
    public void setDuration(int milliseconds)
    {
    	this.duration = Util.timeIntToString(milliseconds);    	
    }
    
    
    
    public String getDurationString() {
    	
    	return this.duration;
    }
    
    
    
    /* 
     * Returns the duration in milliseconds
     */
    public int getDurationInt()
    {
    	int duration = 0;
    	
    	if (this.duration != null)
    	{
	    	Matcher m = DURATION_PATTERN.matcher(this.duration);
	    	
	    	if (m.matches() && m.groupCount() >= 3) {
	    		
	    		int hours = 0;
	    		int minutes = 0;
	    		int seconds = 0;
	    		
	    		try
	    		{
	    			String group1 = m.group(1);

	                if (group1 == null || group1.equals("")) {
	                    group1 = "0";
	                }
	                else if (group1.contains(":")) {
	                    group1 = group1.replaceAll(":", "");
	                }
	                
		    		hours = Integer.parseInt(group1);
		    		minutes = Integer.parseInt(m.group(2));
		    		seconds = Integer.parseInt(m.group(3));
	    		}
	    		catch (NumberFormatException e) {
	    			Log.e("Item", "caught NumberFormatException parsing \""+this.duration+"\" for item: "+this.title);
	    			e.printStackTrace();
	    		}
	    		
	    		duration = hours*3600000 + minutes*60000 + seconds*1000;
	    	}
    	}
    	
    	return duration;
    }
    
    
    
    public String getPubDate() {
    	
    	return this.pubDate;
    }
    
    
    
    public String getSize()
    {
    	float kb = size/1024.0f;
    	
    	if (kb > 0.0) {
    		
    		float mb = size/1048576.0f;
    		
    		if (mb > 0.0) {
    			
    			return String.format("%.2f MB", mb-0.005f);
    		}
    		
    		return String.format("%.2f KB", kb-0.005f);
    	}
    	
    	return String.format("%d B", size);
    }


	@Override
	public int describeContents() {
		return 0;
	}


	@Override
	public void writeToParcel(Parcel out, int flags) {
		
		out.writeString(guid);
		out.writeInt(channel_id);
		out.writeString(title);
		out.writeString(pubDate);
		out.writeInt((listened ? 1 : 0));
		out.writeInt(position);
		out.writeInt(size);
		out.writeString(duration);
		out.writeString(enclosureURL);
		out.writeString(description);
	}
    
	
	
	/**
    * This field is needed for Android to be able to
    * create new objects, individually or as arrays.
    */
   public static final Parcelable.Creator<Item> CREATOR =
		   new Parcelable.Creator<Item>() {
	           public Item createFromParcel(Parcel in) {
	               return new Item(in);
	           }
	           public Item[] newArray(int size) {
	               return new Item[size];
	           }
   };


}
